home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 1 / Gold Medal Software Volume 1 (Gold Medal) (1994).iso / prog / pcl4c40.arj / TERM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-18  |  13.0 KB  |  446 lines

  1. /*
  2. **                    --- term.c ---
  3. **
  4. **  EXAMPLE CODE: Terminal emulator. Can transfer files using
  5. **  ASCII, XMODEM, YMODEM, and YMODEM-G protocols.
  6. **
  7. **  See TERM.CFG for configuration parameters.
  8. **
  9. **  Link with TERM_IO, MODEM_IO, DIR_IO, CRC, DOS, AMODEM, XYMODEM,
  10. **  and XYPACKET. See TERM makefiles.
  11. **
  12. **  Do NOT select YMODEM-G when using a null modem cable unless you are
  13. **  certain that RTS & CTS are reversed ( this is usually not true ).
  14. **
  15. **  This example program (not the PCL4C library) is donated to
  16. **  the Public Domain by MarshallSoft Computing, Inc. It is
  17. **  provided as an example of the use of the PCL4C.
  18. **
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <ctype.h>
  24. #include <fcntl.h>
  25. #include <string.h>
  26. #include <sys\types.h>
  27. #include <sys\stat.h>
  28. #include "pcl4c.h"
  29. #include "ascii.h"
  30. #include "term.h"
  31. #include "dir_io.h"
  32. #include "term_io.h"
  33. #include "dos_io.h"
  34. #include "modem_io.h"
  35. #include "crc.h"
  36. #include "xymodem.h"
  37. #include "amodem.h"
  38. #include "term.h"
  39. #include "term.cfg"
  40.  
  41. #define FALSE 0
  42. #define TRUE !FALSE
  43. #define NORMAL 0x07
  44. #define INVERSE 0x70
  45. #define MESSAGE_POS 48
  46.  
  47. /* local prototypes */
  48. void MyStart(int Port,int BaudCode);
  49. int BaudMatch(char *ptr);
  50. void ProcessESC(void);
  51. void ShowMessage(int Pos,char *Msg);
  52. void ShowProtocol(void);
  53. void SayFilename(char *Text);
  54.  
  55.  
  56. /*** Global variables ***/
  57.  
  58. #define RX_BUFFER_SIZE 2048
  59. #define TX_BUFFER_SIZE 2048
  60.  
  61. int Port;               /* current COM port [0..3] */
  62. char FileSpec[15];      /* file name specification */
  63. char Filename[15];      /* file name buffer */
  64. char Buffer[1024];      /* block buffer */
  65. char RxBuf[RX_BUFFER_SIZE];  /* receive buffer */
  66. char TxBuf[TX_BUFFER_SIZE];  /* transmit buffer */
  67. char *BaudRate[10] =  {"300","600","1200","2400","4800","9600",
  68.                        "19200","38400","57600","115200"};
  69. int BaudCode;           /* baud rate code ( index into BaudRate[] ) */
  70. char *ModelText[4] = {"Small","Compact","Medium","Large"};
  71. char NCGchar   = NAK;
  72. int  OneKflag  = FALSE;
  73. int  BatchFlag = FALSE;
  74. char Protocol  = 'X';
  75. char TermChar  = 0x00;
  76. int  CharPace  = 0;
  77. int  Timeout   = 10;
  78. int  EchoFlag  = TRUE;
  79.  
  80. /*** main program ***/
  81.  
  82. void main(int argc,char *argv[])
  83. {int DataFlag = FALSE;
  84.  char c;
  85.  int i, k;
  86.  int n, rc;
  87.  int Delta;         /* delta port status */
  88.  int Status;        /* port status */
  89.  char Version;
  90.  char temp[81];
  91.  /* right number of parameters ? */
  92.  if(argc!=3)
  93.      {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600'\n");
  94.       exit(1);
  95.      }
  96.  /* get port number from command line */
  97.  Port = atoi(argv[1]) - 1;
  98.  if((Port<0) || (Port>11))
  99.      {printf("Port must be 1 to 12\n");
  100.       exit(1);
  101.      }
  102.  /* get baud rate from command line */
  103.  BaudCode = BaudMatch(argv[2]);
  104.  if(BaudCode<0)
  105.      {printf("Cannot recognize baud rate = %s\n",argv[2]);
  106.       exit(1);
  107.      }
  108. #if 0
  109.  /*** Custom Configuration: 4 port card ***/
  110.  SioIRQ(COM1,IRQ4);
  111.  SioIRQ(COM2,IRQ3);
  112.  /* use IRQ2 for COM3 & COM4 */
  113.  SioIRQ(COM3,IRQ2);
  114.  SioIRQ(COM4,IRQ2);
  115. #endif
  116. #if 0
  117.  /*** Custom Configuration: DigiBoard PC/8 ***/
  118.  puts("Configuring DigiBoard as COM1-COM8 (IRQ5)");
  119.  SioDelay(18);
  120.  /* use 0x140 for even IRQs & 0x141 for odd IRQs */
  121.  SioPorts(8,COM1,0x140);
  122.  /* set DigiBoard UART addresses */
  123.  ErrorCheck( SioUART(Port,0x100+8*Port) );
  124.  /* set DigiBoard for IRQ5 */
  125.  ErrorCheck( SioIRQ(Port,IRQ5) );
  126. #endif
  127.  /* setup receive buffer */
  128.  ErrorCheck( SioRxBuf(Port,RxBuf,Size2K) );
  129. #if 1
  130.  /* setup transmit buffer */
  131.  ErrorCheck( SioTxBuf(Port,TxBuf,Size2K) );
  132. #endif
  133.  /* set parms & reset (initialize) COM port */
  134.  ErrorCheck( SioParms(Port,NoParity,OneStopBit,WordLength8) );
  135.  MyStart(Port,BaudCode);
  136.  /* set DTR and RTS */
  137.  SioDTR(Port,'S');
  138.  SioRTS(Port,'S');
  139.  /* init CRC table */
  140.  InitCRC();
  141.  /* initialize screen */
  142.  Scroll(0,0,24,79,0,NORMAL);
  143.  /* display status message */
  144.  sprintf(temp," COM%d %s %c 'ESC for menu'  ",1+Port,BaudRate[BaudCode],Protocol);
  145.  ShowMessage(0,temp);
  146.  Position(1,0);
  147.  /* display some info */
  148.  puts("TERM 10/1/93");
  149.  Version = SioInfo('V');
  150.  printf("Library = %d.%d\n",Version/16,Version%16);
  151.  printf("Memory Model = %s\n",ModelText[3&SioInfo('M')] );
  152. #if RTS_CTS_CONTROL
  153.  SioFlow(Port,7*ONE_SECOND);
  154.  printf("Flow Control enabled. CTS = ");
  155.  if(SioCTS(Port)) puts("ON");
  156.  else puts("OFF");
  157. #endif
  158.  /* Set FIFO level */
  159.  if( SioFIFO(Port,LEVEL_14) ) puts("INS16550 detected");
  160.  /* clear PCL4C receive buffer */
  161.  ErrorCheck( SioRxFlush(Port) );
  162.  
  163.  /* see TERM.H for definition of AT_COMMAND_SET */
  164. #if AT_COMMAND_SET
  165.  /* wait for Modem to say its ready */
  166.  printf("Waiting for Modem DSR.");
  167.  while( !SioDSR(Port) )
  168.      {
  169.       if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
  170.       putchar('.');
  171.       SioDelay(18);
  172.      }
  173.  putchar('\n');
  174.  /* initialize (Hayes compatible) modem */
  175.  SendTo(Port,"!AT!!~");
  176.  SendTo(Port,"!AT E1 S7=60 S11=60 V1 X1 Q0 S0=1!");
  177.  if(WaitFor(Port,"OK")) printf("\nMODEM READY\n");
  178.  else printf("\nWARNING: Expected OK not received\n");
  179. #endif
  180.  
  181.  /* enter terminal loop */
  182.  SioRxFlush(Port);
  183.  while(1)
  184.      {/* Control-BREAK ? */
  185.       if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
  186.       /* was key pressed ? */
  187.       if(SioKeyPress())
  188.           {/* read key press */
  189.            i = SioKeyRead();
  190.            if((char)i==ESC)
  191.                {/* process user's request */
  192.                 ProcessESC();
  193.                 ShowMessage(strlen(BaudRate[BaudCode])+9,"'ESC for Menu' ");
  194.                 continue;
  195.                }
  196.            else PutChar(Port,(char)i);
  197.           }
  198.       /* was break detected ? */
  199.       if( SioBrkSig(Port,'D') ) DisplayLine("BREAK detected ",NULL,0);
  200.       /* any incoming over serial port ? */
  201.       i = GetChar(Port,(char)0);
  202.       if(i>-1)
  203.           {/* good character */
  204.            if(DataFlag&((i<0x20)||(i>0x7e)))
  205.                {MyCrtWrite('^');
  206.                 MyCrtWrite((char)('@'+i));
  207.                }
  208.            else MyCrtWrite((char)i);
  209.           }
  210.       /* any change in DCD or DSR ? */
  211.       Delta = SioModem(Port,DeltaDCD|DeltaDSR);
  212.       if(Delta)
  213.           {/* display new status */
  214.            Status = SioModem(Port,(char)(DCD|DSR));
  215.            if(!Status&DeltaDCD) MyExit(0,"Dropped DSD");
  216.            if(!Status&DeltaDSR) MyExit(0,"Dropped DSR");
  217.           }
  218.      } /* end -- key pressed */
  219. }
  220.  
  221. /*** write to screen except for bottom line ***/
  222.  
  223. void MyCrtWrite(char ch)
  224. {/* write character */
  225.  SioCrtWrite(ch);
  226.  /* scroll all but bottom line */
  227.  if(GetRow()==24)
  228.     {Scroll(0,0,23,79,1,NORMAL);
  229.      Position(23,0);
  230.     }
  231. }
  232.  
  233. /*** make multiple attempts to reset port ***/
  234.  
  235. void MyStart(int Port,int BaudCode)
  236. {int i, rc;
  237.  /* try up to 3 times to reset COM port */
  238.  for(i=0;i<3;i++)
  239.      {printf("Resetting COM%d at %s baud\n",Port+1,BaudRate[BaudCode]);
  240.       if( (rc = SioReset(Port,BaudCode))==0) return;
  241.       if(rc<0) MyExit(rc,"Error resetting port");
  242.       SioDone(Port);
  243.       /* display errors */
  244.       if(rc&OverrunError) puts("Overrun Error");
  245.       if(rc&ParityError)  puts("Parity Error");
  246.       if(rc&FramingError) puts("Framing Error");
  247.       if(rc&BreakDetect)  puts("Break Detect");
  248.      }
  249.  exit(1);
  250. }
  251.  
  252. /*** find baud rate string in table ***/
  253.  
  254. int BaudMatch(char *ptr)
  255. {int i;
  256.  /* find baud rate in table */
  257.  for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
  258.  return(-1);
  259. }
  260.  
  261. /*** user pressed Escape */
  262.  
  263. void ProcessESC(void)
  264. {int i;
  265.  int rc;
  266.  int c1, c2;
  267.  char Answer[2]; /* array for 1 char answer */
  268.  int row, col;
  269.  /* user pressed <ESC> */
  270.  Answer[0] = '?';
  271.  Answer[1] = '\0';
  272.  DisplayLine("Q)uit P)rotocol S)end R)eceive: ",Answer,1);
  273.  if(strlen(Answer)) switch(toupper(Answer[0]))
  274.      {
  275.       case 'P':
  276. #if RTS_CTS_CONTROL
  277.           DisplayLine("A)scii X)modem Y)modem ymodem-G): ",Answer,1);
  278. #else
  279.           DisplayLine("A)scii X)modem Y)modem: ",Answer,1);
  280. #endif
  281.           if(strlen(Answer)) switch( toupper(Answer[0]) )
  282.                {
  283.                 case 'A':
  284.                     Protocol = 'A';
  285.                     ShowProtocol();
  286.                     TermChar = 0x18;  /* CAN or control-X */
  287.                     CharPace = 0;     /* no inter-byte delay */
  288.                     Timeout = 7;      /* timeout after 7 seconds */
  289.                     EchoFlag = TRUE;  /* do local echo */
  290.                     DisplayLine("Protocol = ASCII",NULL,1);
  291.                     break;
  292.                 case 'X':
  293.                     Protocol = 'X';
  294.                     ShowProtocol();
  295.                     OneKflag = FALSE;
  296.                     BatchFlag = FALSE;
  297.                     NCGchar = NAK;
  298.                     DisplayLine("Protocol = XMODEM",NULL,1);
  299.                     break;
  300.                 case 'Y':
  301.                     Protocol = 'Y';
  302.                     ShowProtocol();
  303.                     OneKflag = TRUE;
  304.                     BatchFlag = TRUE;
  305.                     NCGchar = 'C';
  306.                     DisplayLine("Protocol = YMODEM",NULL,1);
  307.                     break;
  308. #if RTS_CTS_CONTROL
  309.                 case 'G':
  310.                     Protocol = 'G';
  311.                     ShowProtocol();
  312.                     OneKflag = TRUE;
  313.                     BatchFlag = TRUE;
  314.                     NCGchar = 'G';
  315.                     DisplayLine("Protocol = YMODEM-G",NULL,1);
  316.                     break;
  317. #endif
  318.                 default:
  319.                     DisplayLine("Must answer X, Y, or G",NULL,1);
  320.                     break;
  321.                }
  322.           break;
  323.       case 'Q':
  324.           MyExit(0,"User pressed ESC");
  325.           break;
  326.       case 'R':
  327.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  328.           if(Protocol=='A')
  329.               {/* Ascii */
  330.                DisplayLine("Enter filename:",Filename,15);
  331.                if(strlen(Filename)==0) break;
  332.                RxAscii(Port,Filename,Buffer,1024,RX_BUFFER_SIZE,FALSE,TermChar,Timeout,EchoFlag);
  333.                break;
  334.               }
  335.           /* XMODEM / YMODEM receive */
  336.           if(BatchFlag)
  337.                {do
  338.                     {/* receive files till get empty filename */
  339.                      RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  340.                      if(SioKeyPress()) break;
  341.                     } while(Filename[0]!='\0');
  342.                }
  343.           else /* not Batch */
  344.                {DisplayLine("Enter filename:",Filename,15);
  345.                 if(strlen(Filename)==0) break;
  346.                 RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  347.                }
  348.           break;
  349.       case 'S':
  350.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  351.           DisplayLine("Enter filename:",FileSpec,15);
  352.           if(strlen(FileSpec)==0) break;
  353.           if(Protocol=='A')
  354.               {/* Ascii */
  355.                TxAscii(Port,FileSpec,Buffer,1024,FALSE,CharPace,TermChar,EchoFlag);
  356.                break;
  357.               }
  358.           if(BatchFlag)
  359.                {/* YMODEM send */
  360.                 if(FindFirst(FileSpec,Filename))
  361.                   {SayFilename(Filename);
  362.                    TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  363.                    while(FindNext(Filename))
  364.                      {SioDelay(4);
  365.                       SayFilename(Filename);
  366.                       TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  367.                      }
  368.                    /* send empty filename */
  369.                    Filename[0] = '\0';
  370.                    SioDelay(5);
  371.                    TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  372.                   }
  373.                }
  374.           else
  375.                {/* XMODEM send */
  376.                 TxyModem(Port,FileSpec,Buffer,OneKflag,BatchFlag);
  377.                }
  378.           break;
  379.      default:
  380.           DisplayLine("Must answer Q, P, S, or R",NULL,0);
  381.           break;
  382.     } /* end switch */
  383. }
  384.  
  385. /*** show protocol choosen ***/
  386.  
  387. void ShowProtocol(void)
  388. {int SaveRow;
  389.  int SaveCol;
  390.  SaveRow = GetRow();
  391.  SaveCol = GetCol();
  392.  Position(24,(unsigned char)(MESSAGE_POS+strlen(BaudRate[BaudCode])+7));
  393.  AttrWrite(Protocol,INVERSE);
  394.  Position((unsigned char)SaveRow,(unsigned char)SaveCol);
  395. }
  396.  
  397. /*** show chosen message ***/
  398.  
  399. void ShowMessage(int Pos,char *Msg)
  400. {int i;
  401.  int SaveRow;
  402.  int SaveCol;
  403.  int Col;
  404.  SaveRow = GetRow();
  405.  SaveCol = GetCol();
  406.  Col = MESSAGE_POS+Pos;
  407.  for(i=0;i<strlen(Msg);i++)
  408.    {Position(24,(unsigned char)Col++);
  409.     AttrWrite(Msg[i],INVERSE);
  410.    }
  411.  Position((unsigned char)SaveRow,(unsigned char)SaveCol);
  412. }
  413.  
  414. /*** exit program ***/
  415.  
  416. void MyExit(int code, char *msg)
  417. {int rc;
  418.  if(code<0) SioError(code);
  419.  /* Assert UART break & sign off */
  420.  SioBrkSig(Port,'A');
  421.  printf("\nTERMINATING: %s\n",msg);
  422.  SioDelay(ONE_SECOND/2);
  423.  SioDone(Port);
  424.  exit(0);
  425. }
  426.  
  427. /*** display file name in status area ***/
  428.  
  429. void SayFilename(char *Text)
  430. {char Temp[40];
  431.  strcpy(Temp,"Sending ");
  432.  strcat(Temp,Text);
  433.  DisplayLine(Temp,NULL,0);
  434.  SioDelay(ONE_SECOND/2);
  435. }
  436.  
  437. /*** check for error ***/
  438.  
  439. void ErrorCheck(int Code)
  440. {/* trap PCL error codes */
  441.  if(Code<0)
  442.      {SioError(Code);
  443.       SioDone(Port);
  444.       exit(1);
  445.      }
  446. } /* end ErrorCheck */